package edu.tsp.ga.crossover;

import edu.tsp.ga.Chromosome;
import edu.tsp.ga.Gene;
import edu.tsp.ga.utils.Pair;
import edu.tsp.ga.utils.RandomGenerator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CycleCrossover implements Crossover {
    @Override
    public Pair<Chromosome, Chromosome> crossover(Chromosome c1, Chromosome c2) {
        Pair<List<Gene>, List<Gene>> offspring =
                cycleCrossover(c1.getGenes(), c2.getGenes(), RandomGenerator.nextInt(c1.getGenes().size()));
        return new Pair<>(new Chromosome(offspring.head), new Chromosome(offspring.tail));
    }

    private <T> Pair<List<T>,List<T>> cycleCrossover(List<T> genes1, List<T> genes2, int startIndex) {
        List<T> offspring1 = new ArrayList<>(genes1);
        List<T> offspring2 = new ArrayList<>(genes2);
        List<Integer> route = new ArrayList<>();
        T g2 = genes2.get(startIndex);
        route.add(startIndex);
        int index = genes1.indexOf(g2);
        while(index != startIndex) {
            route.add(index);
            g2 = genes2.get(index);
            index = genes1.indexOf(g2);
        }
        for(int i : route) {
            T temp = offspring1.get(i);
            offspring1.set(i, offspring2.get(i));
            offspring2.set(i, temp);
        }
        return new Pair<>(offspring1, offspring2);
    }

    public static void main(String args[]) {
        List<Integer> i1 = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8));
        List<Integer> i2 = new ArrayList<>(Arrays.asList(3,7,5,1,4,8,2,6));
        List<Gene> ii1 = i1.stream().map(Gene::new).collect(Collectors.toList());
        List<Gene> ii2 = i2.stream().map(Gene::new).collect(Collectors.toList());
        CycleCrossover crossover = new CycleCrossover();
        System.out.println(crossover.cycleCrossover(i1,i2,3));
        System.out.println(crossover.cycleCrossover(ii1,ii2,3));
    }

}
